<template>
  <div :style="{position: 'relative', width: contentWidth + widthPixelUnit, height: contentHeight + heightPixelUnit}">

    <div class="ScaleRuler_h" v-show="topScaleRulerHAndVShow" :style="{width: topScaleRulerHWidth}" style="z-index: 2; position: sticky; top: 0px;" @mousedown.stop="levelDragRuler">
      <span v-for="(item,index) in xScale" :key="index" :style="{left:index * 50 + 2 + 'px'}" class="n">{{ item.id }}</span>
    </div>
    <div class="ScaleRuler_v" v-show="topScaleRulerHAndVShow" :style="{height: topScaleRulerVHeight}" style="z-index: 2; position: sticky; left: 0px;" @mousedown.stop="verticalDragRuler">
      <span v-for="(item,index) in yScale" :key="index" :style="{top:index * 50 + 2 + 'px'}" class="n">{{ item.id }}</span>
    </div>

    <div id="rulerTool" :style="{width : rulerToolWidth, height : rulerToolHeight, position: 'absolute', top: '0px'}" class="ScaleBox" onselectstart="return false;">
      <section v-show="rulerToggle">
        <div id="levelRuler" class="ScaleRuler_h" style="z-index: 1" @mousedown.stop="levelDragRuler">
          <span v-for="(item,index) in xScale" :key="index" :style="{left:index * 50 + 2 + 'px'}" class="n">{{ item.id }}</span>
        </div>
        <div id="verticalRuler" class="ScaleRuler_v" style="z-index: 1" @mousedown.stop="verticalDragRuler">
          <span v-for="(item,index) in yScale" :key="index" :style="{top:index * 50 + 2 + 'px'}" class="n">{{ item.id }}</span>
        </div>

        <!--横向虚线-->
        <div id="levelDottedLine" :style="{top:verticalDottedTop + 'px'}" class="RefDot_h">
          <div class="dot-line-action">
            <span>{{verticalDottedTop - 17}}</span>
          </div>
        </div>
        <!--纵向虚线-->
        <div id="verticalDottedLine" :style="{left:levelDottedLeft + 'px'}" class="RefDot_v">
          <div class="dot-line-action">
            <span>{{levelDottedLeft - 17}}</span>
          </div>
        </div>

        <div v-for="item in levelLineList" :id="item.id" :title="item.title" :style="{top:item.top+ 'px'}" :key="item.id" class="RefLine_h" @mousedown="dragLevelLine(item.id)" >
          <div class="line-action">
            <span>{{item.title}}</span>
          </div>
        </div>
        <div v-for="item in verticalLineList" :id="item.id" :title="item.title" :style="{left:item.left+ 'px'}" :key="item.id" class="RefLine_v" @mousedown="dragVerticalLine(item.id)" >
          <div class="line-action">
            <span>{{item.title}}</span>
          </div>
        </div>
      </section>
      <div id="content" :style="{width: contentWidth + widthPixelUnit, height: contentHeight + heightPixelUnit, left: '0px', top: '0px', padding: '18px 0px 0px 18px'}">
        <slot />
      </div>
    </div>
  </div>
</template>

<script>

  import { createHelpers } from 'vuex-map-fields';

  const { mapFields } = createHelpers({
    getterType: 'designer/getField',
    mutationType: 'designer/updateField',
  });

  export default {
    name: 'VueRulerTool',
    components: {},
    props: {
      position: {
        type: String,
        default: 'relative',
        validator: function (val) {
          return ['absolute', 'fixed', 'relative', 'static', 'inherit'].indexOf(val) !== -1
        }
      }, // 规定元素的定位类型
      isHotKey: {
        type: Boolean, default: true
      }, // 热键开关
      isScaleRevise: {
        type: Boolean, default: false
      }, // 刻度修正(根据content进行刻度重置)
      presetLine: {
        type: Array,
        default: () => {
          return [] // { type: 'l', site: 50 }, { type: 'v', site: 180 }
        }
      }, // 预置参考线
      contentLayout: {
        type: Object,
        default: () => {
          return { top: 0, left: 0 }
        }
      }, // 内容部分布局
      parent: {
        type: Boolean,
        default: false
      },
      contentWidth: {
        type: Number
      },
      widthPixelUnit: {
        type: String
      },
      contentHeight: {
        type: Number
      },
      heightPixelUnit: {
        type: String
      }
    },
    data () {
      return {
        size: 17,
        left_top: 18, // 内容左上填充
        windowWidth: 0, // 窗口宽度
        windowHeight: 0, // 窗口高度
        xScale: [], // 水平刻度
        yScale: [], // 垂直刻度
        topSpacing: 0, // 标尺与窗口上间距
        leftSpacing: 0, //  标尺与窗口左间距
        isDrag: false,
        dragFlag: '', // 拖动开始标记，可能值x(从水平标尺开始拖动),y(从垂直标尺开始拖动)
        levelLineList: [], // 生成的水平线列表
        verticalLineList: [], // 生成的垂直线列表
        levelDottedLeft: -999, // 水平虚线位置
        verticalDottedTop: -999, // 垂直虚线位置
        rulerWidth: 0, // 垂直标尺的宽度
        rulerHeight: 0, // 水平标尺的高度
        dragLineId: '', // 被移动线的ID
        keyCode: {
          r: 82
        }, // 快捷键参数
        rulerToggle: true, // 标尺辅助线显示开关
      }
    },
    watch: {
      'pageMetadata.id': {
        handler: function (val, oldVal) {
          this.loadLines()
        }
      }
    },
    mounted () {
      document.documentElement.addEventListener('mousemove', this.dottedLineMove, true);
      document.documentElement.addEventListener('mouseup', this.dottedLineUp, true);
      document.documentElement.addEventListener('keyup', this.keyboard, true);
      this.init();
      this.quickGeneration(this.presetLine) // 生成预置参考线
      const self = this; // 绑定窗口调整大小onresize事件
      window.onresize = function () { // 如果直接使用this,this指向的不是vue实例
        self.xScale = [];
        self.yScale = [];
        self.init()
      };
    },
    beforeDestroy: function () {
      document.documentElement.removeEventListener('mousemove', this.dottedLineMove, true);
      document.documentElement.removeEventListener('mouseup', this.dottedLineUp, true);
      document.documentElement.removeEventListener('keyup', this.keyboard, true)
    },
    methods: {
      init () {
        this.box();
        this.scaleCalc();
        this.loadLines()
      },
      box () {
        if (this.isScaleRevise) { // 根据内容部分进行刻度修正
          const content = document.getElementById('content');
          const contentLeft = content.offsetLeft;
          const contentTop = content.offsetTop;
          for (let i = 0; i < contentLeft; i += 1) {
            if (i % 50 === 0 && i + 50 <= contentLeft) {
              this.xScale.push({ id: i })
            }
          }
          for (let i = 0; i < contentTop; i += 1) {
            if (i % 50 === 0 && i + 50 <= contentTop) {
              this.yScale.push({ id: i })
            }
          }
        }
        if (this.parent) {
          const style = window.getComputedStyle(this.$el.parentNode, null);
          this.windowWidth = parseInt(style.getPropertyValue('width'), 10);
          this.windowHeight = parseInt(style.getPropertyValue('height'), 10)
        } else {
          this.windowWidth = document.documentElement.clientWidth - this.leftSpacing;
          this.windowHeight = document.documentElement.clientHeight - this.topSpacing
        }
        this.rulerWidth = document.getElementById('verticalRuler').clientWidth;
        this.rulerHeight = document.getElementById('levelRuler').clientHeight;
        this.setSpacing()
      }, // 获取窗口宽与高
      setSpacing () {
        this.topSpacing = document.getElementById('levelRuler').getBoundingClientRect().y; //.offsetParent.offsetTop
        this.leftSpacing = document.getElementById('verticalRuler').getBoundingClientRect().x// .offsetParent.offsetLeft
      },
      scaleCalc () {
        for (let i = 0; i < 20000; i += 1) {
          if (i % 50 === 0) {
            this.xScale.push({ id: i })
          }
        }
        for (let i = 0; i < 20000; i += 1) {
          if (i % 50 === 0) {
            this.yScale.push({ id: i })
          }
        }
      }, // 计算刻度
      newLevelLine () {
        this.isDrag = true;
        this.dragFlag = 'x'
      }, // 生成一个水平参考线
      newVerticalLine () {
        this.isDrag = true;
        this.dragFlag = 'y'
      }, // 生成一个垂直参考线
      dottedLineMove ($event) {
        this.setSpacing();
        switch (this.dragFlag) {
          case 'x':
            if (this.isDrag) {
              this.verticalDottedTop = $event.pageY - this.topSpacing
            }
            break;
          case 'y':
            if (this.isDrag) {
              this.levelDottedLeft = $event.pageX - this.leftSpacing
            }
            break;
          case 'l':
            if (this.isDrag) {
              this.verticalDottedTop = $event.pageY - this.topSpacing
            }
            break;
          case 'v':
            if (this.isDrag) {
              this.levelDottedLeft = $event.pageX - this.leftSpacing
            }
            break;
          default:
            break
        }
      }, // 虚线移动
      dottedLineUp ($event) {
        this.setSpacing();
        if (this.isDrag) {
          this.isDrag = false;
          switch (this.dragFlag) {
            case 'x':
              this.levelLineList.push(
                {
                  id: 'levelLine' + this.levelLineList.length + 1,
                  title: $event.pageY - this.topSpacing - this.size,
                  top: $event.pageY - this.topSpacing
                }
              );
              break;
            case 'y':
              this.verticalLineList.push(
                {
                  id: 'verticalLine' + this.verticalLineList.length + 1,
                  title: $event.pageX - this.leftSpacing - this.size,
                  left: $event.pageX - this.leftSpacing
                }
              );
              break;
            case 'l':
              if ($event.pageY - this.topSpacing < this.rulerHeight) {
                let Index, id;
                this.levelLineList.forEach((item, index) => {
                  if (item.id === this.dragLineId) {
                    Index = index;
                    id = item.id
                  }
                });
                this.levelLineList.splice(Index, 1, {
                  id: id,
                  title: -600 + 'px',
                  top: -600
                })
              } else {
                let Index, id;
                this.levelLineList.forEach((item, index) => {
                  if (item.id === this.dragLineId) {
                    Index = index;
                    id = item.id
                  }
                });
                this.levelLineList.splice(Index, 1, {
                  id: id,
                  title: $event.pageY - this.topSpacing - this.size,
                  top: $event.pageY - this.topSpacing
                })
              }
              break;
            case 'v':
              if ($event.pageX - this.leftSpacing < this.rulerWidth) {
                let Index, id;
                this.verticalLineList.forEach((item, index) => {
                  if (item.id === this.dragLineId) {
                    Index = index;
                    id = item.id
                  }
                });
                this.verticalLineList.splice(Index, 1, {
                  id: id,
                  title: -600 + 'px',
                  left: -600
                })
              } else {
                let Index, id;
                this.verticalLineList.forEach((item, index) => {
                  if (item.id === this.dragLineId) {
                    Index = index
                    id = item.id
                  }
                });
                this.verticalLineList.splice(Index, 1, {
                  id: id,
                  title: $event.pageX - this.leftSpacing - this.size,
                  left: $event.pageX - this.leftSpacing
                })
              }
              break;
            default:
              break
          }
          this.verticalDottedTop = this.levelDottedLeft = -500;
          this.saveLines()
        }
      }, // 虚线松开
      levelDragRuler () {
        this.newLevelLine()
      }, // 水平标尺处按下鼠标
      verticalDragRuler () {
        this.newVerticalLine()
      }, // 垂直标尺处按下鼠标
      dragLevelLine (id) {
        this.isDrag = true;
        this.dragFlag = 'l';
        this.dragLineId = id
      }, // 水平线处按下鼠标
      dragVerticalLine (id) {
        this.isDrag = true;
        this.dragFlag = 'v';
        this.dragLineId = id
      }, // 垂直线处按下鼠标
      keyboard ($event) {
        if (this.isHotKey) {
          switch ($event.keyCode) {
            case this.keyCode.r:
              this.rulerToggle = !this.rulerToggle;
              if (this.rulerToggle) {
                this.left_top = 18;
              } else {
                this.left_top = 0;
              }
              break
          }
        }
      }, // 键盘事件
      quickGeneration (params) {
        if (params !== []) {
          params.forEach(item => {
            switch (item.type) {
              case 'l':
                this.levelLineList.push({
                  id: 'levelLine' + this.levelLineList.length + 1,
                  title: item.site + 'px',
                  top: item.site + this.size
                });
                break;
              case 'v':
                this.verticalLineList.push({
                  id: 'verticalLine' + this.verticalLineList.length + 1,
                  title: item.site + 'px',
                  left: item.site + this.size
                });
                break;
              default:
                break
            }
          })
        }
      }, // 快速生成参考线
      clearLines () {
        let currentPageId = this.pageMetadata.id;

        if (localStorage.getItem('pageGuidesData')) {
          let pageGuidesData = JSON.parse(localStorage.getItem('pageGuidesData'));
          if (pageGuidesData[currentPageId]) {
            delete pageGuidesData[currentPageId];
            localStorage.setItem('pageGuidesData', JSON.stringify(pageGuidesData));
            this.loadLines();
          }
        }

      }, // 清空参考线
      toggleLinesDisplay (display) {
        if (display) {
          if (display == 'show')
            this.rulerToggle = true;
          else if (display == 'hide')
            this.rulerToggle = false;
        }else {
          this.rulerToggle = !this.rulerToggle;
        }
      }, // 切换参考线显示隐藏
      saveLines () {
        let currentPageId = this.pageMetadata.id;

        if (localStorage.getItem('pageGuidesData')) {
          let pageGuidesData = JSON.parse(localStorage.getItem('pageGuidesData'));
          pageGuidesData[currentPageId] = {
            'levelLineList': this.levelLineList,
            'verticalLineList': this.verticalLineList
          };
          localStorage.setItem('pageGuidesData', JSON.stringify(pageGuidesData));
        }else {
          let newPageGuidesData = {
            [currentPageId]: {
              'levelLineList': this.levelLineList,
              'verticalLineList': this.verticalLineList
            }
          };
          localStorage.setItem('pageGuidesData', JSON.stringify(newPageGuidesData));
        }

        // this.$Message.success('成功将当前设置参考线方案保存至浏览器本地存储中')
      },
      loadLines () {
        let currentPageId = this.pageMetadata.id;

        if (localStorage.getItem('pageGuidesData')) {
          let pageGuidesData = JSON.parse(localStorage.getItem('pageGuidesData'));
          if (pageGuidesData[currentPageId]) {
            this.levelLineList = pageGuidesData[currentPageId].levelLineList;
            this.verticalLineList = pageGuidesData[currentPageId].verticalLineList;
          }else {
            this.levelLineList = [];
            this.verticalLineList = [];
          }
        }
      },
    },
    computed: {
      ...mapFields({
        pageMetadata: 'pageMetadata'
      }),
      rulerToolWidth () {
        if(this.widthPixelUnit == 'px') {
          return (this.contentWidth + 18) + this.widthPixelUnit
        }else if (this.widthPixelUnit == '%') {
          return this.contentWidth + this.widthPixelUnit
        }
        return ''
      },
      rulerToolHeight () {
        if(this.heightPixelUnit == 'px') {
          return (this.contentHeight + 18) + this.heightPixelUnit
        }else if (this.heightPixelUnit == '%') {
          return this.contentHeight + this.heightPixelUnit
        }
        return ''
      },
      topScaleRulerHWidth () {
        if(this.widthPixelUnit == 'px') {
          return (this.contentWidth + 18) + this.widthPixelUnit
        }else if (this.widthPixelUnit == '%') {
          return this.contentWidth + this.widthPixelUnit
        }
        return ''
      },
      topScaleRulerVHeight () {
        if(this.heightPixelUnit == 'px') {
          return this.contentHeight + this.heightPixelUnit
        }else if (this.heightPixelUnit == '%') {
          return (this.contentHeight - 18) + this.heightPixelUnit
        }
        return ''
      },
      topScaleRulerHAndVShow () {
        if (this.$parent.zoomValue != 1) {
          return false
        }
        return true
      }
    }
  }
</script>

<style scoped>
  .ScaleBox {
    left: 0;
    top: 0;
    z-index: 1;
    overflow: hidden;
    user-select: none;
  }

  .ruler-toggle-btn {
    position: absolute;
    top: 0px;
    width: 18px;
    height: 18px;
    z-index: 11;
    text-align: center;
    color: #fff;
    background-color: #535353;
    border-right: 1px solid #424242;
    border-bottom: 1px solid #424242;
  }

  .ScaleRuler_h,
  .ScaleRuler_v,
  .RefLine_v,
  .RefLine_h,
  .RefDot_h,
  .RefDot_v {
    position: absolute;
    left: 0;
    top: 0;
    overflow: hidden;
    z-index: 999;
  }

  .ScaleRuler_h {
    width: 100%;
    height: 18px;
    left: 0px;
    opacity: 1;
    background: url()
    repeat-x; /*./image/ruler_h.png*/
    border-left: 18px solid #535353;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -khtml-user-select: none;
    user-select: none;
  }

  .ScaleRuler_v {
    width: 18px;
    height: 100%;
    top: 18px;
    opacity: 1;
    background: url()
    repeat-y; /*./image/ruler_v.png*/
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -khtml-user-select: none;
    user-select: none;
  }

  .ScaleRuler_v .n,
  .ScaleRuler_h .n {
    position: absolute;
    font: 10px/1 Arial, sans-serif;
    color: #fafafa;
    cursor: default;
  }

  .ScaleRuler_v .n {
    width: 8px;
    left: 3px;
    word-wrap: break-word;
  }

  .ScaleRuler_h .n {
    top: 1px;
  }

  .RefLine_v,
  .RefLine_h,
  .RefDot_h,
  .RefDot_v {
    z-index: 998;
  }

  .RefLine_h {
    width: 100%;
    height: 3px;
    background: url()
    repeat-x left center; /*./image/line_h.png*/
    cursor: ns-resize; /*url(./image/cur_move_h.cur), move*/
    position: absolute;
    overflow: inherit;
    overflow-y: visible !important;
    z-index: 3000;
  }

  .RefLine_h .line-action {
    width: auto;
    height: auto;
    background-color: #616161;
    border: 1px solid #424242;
    color: #fff;
    padding: 0px 2px 0px 2px;
    position: absolute;
    top: 2px;
    left: 36px;
    z-index: 3000;
    transform: rotate(90deg);
    transform-origin: 0 0;
    opacity: .6;
  }

  .RefLine_v {
    width: 3px;
    height: 100%;
    _height: 9999px;
    background: url()
    repeat-y center top; /*./image/line_v.png*/
    cursor: ew-resize; /*url(./image/cur_move_v.cur), move*/
    position: absolute;
    overflow: inherit;
    overflow-x: visible !important;
    z-index: 3000;
  }

  .RefLine_v .line-action {
    width: auto;
    height: auto;
    background-color: #616161;
    border: 1px solid #424242;
    color: #fff;
    padding: 0px 2px 0px 2px;
    position: absolute;
    top: 18px;
    left: 2px;
    z-index: 3000;
    opacity: .6;
  }

  .RefDot_h {
    width: 100%;
    height: 30px;
    background: url()
    repeat-x left 1px; /*./image/line_dot.png*/
    cursor: ns-resize; /*url(./image/cur_move_h.cur), move*/
    top: -500px;
  }

  .RefDot_h .dot-line-action {
    position: absolute;
    width: auto;
    height: auto;
    background-color: #616161;
    border: 1px solid #424242;
    color: #fff;
    left: 36px;
    top: 2px;
    z-index: 10;
  }

  .RefDot_v {
    width: 40px;
    height: 100%;
    _height: 9999px;
    background: url()
    repeat-y 1px top; /*./image/line_dot.png*/
    cursor: ew-resize; /*url(./image/cur_move_v.cur), move*/
    left: -10px;
  }

  .RefDot_v .dot-line-action {
    position: absolute;
    width: auto;
    height: auto;
    background-color: #616161;
    padding: 0px 2px 0px 2px;
    border: 1px solid #424242;
    color: #fff;
    top: 36px;
    left: 2px;
    z-index: 10;
  }


  #content {
    position: absolute;
  }
</style>
